using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.Triggers.Properties;

namespace Workflows.Components.Triggers
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class HotFolderTrigger:WorkflowTriggerBase
    {
        private HotFolderOutput _Output;

        private string _HotFolderPath;
        /// <summary></summary>
        public string HotFolderPath
        {
            get
            {
                return this._HotFolderPath;
            }
            set
            {
                this._HotFolderPath = value;
            }
        }

        private string _FileNamePattern;
        /// <summary></summary>
        public string FileNamePattern
        {
            get
            {
                return this._FileNamePattern;
            }
            set
            {
                this._FileNamePattern = value;
            }
        }

        private bool _IncludeSubFolders;
        /// <summary></summary>
        public bool IncludeSubFolders
        {
            get
            {
                return this._IncludeSubFolders;
            }
            set
            {
                this._IncludeSubFolders = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public HotFolderTrigger():base()
        {
            this.ComponentName = "Hot folder";
            this.Description = "Monitor file changes within a folder";
            this.ComponentIcon = Resources.ieframe_206;
            this.ComponentImage = Resources.newdir;
            this.ComponentActivityType = WorkflowActivityType.Trigger;
            this.ComponentCategory = WorkflowComponentCategory.Triggers.ToString();

            this.TriggerType = WorkflowTriggerType.HotFolderTrigger;
            this.TimeSpanUnit = TimeLapseUnit.Week;
            this.Interval = 1;
            this.LastRunTime = DateTime.MinValue;
            this.StartTime = DateTime.Now.AddMinutes(10);
            this.NextRunTime = DateTime.Now.AddDays(1);
            this.IsActive = false;

            this._HotFolderPath = string.Empty;
            this._FileNamePattern = string.Empty;
            this._IncludeSubFolders = false;
            this._Output=new HotFolderOutput(this.ComponentID,Guid.Empty, string.Empty, FileChangeType.Update);
        }

        /// <summary>
        /// only watch for files matched file filter and changed since last successful watch time
        /// </summary>
        /// <param name="lastRunTime"></param>
        /// <returns></returns>
        public override ResultBase[] ProcessTrigger(DateTime lastRunTime)
        {
            List<HotFolderOutput> outputCollection=new List<HotFolderOutput>();
            DirectoryInfo dirInfo = new DirectoryInfo(this.HotFolderPath);
            FileInfo[] files = null;
            if(this.IncludeSubFolders)
            {
                files = dirInfo.GetFiles("*.*", SearchOption.AllDirectories);
            }
            else
            {
                files = dirInfo.GetFiles("*.*", SearchOption.TopDirectoryOnly);
            }
            if(files !=null && files.Length>0)
            {
                foreach(FileInfo file in files)
                {
                    if(file.CreationTime >lastRunTime || file.LastWriteTime >lastRunTime)
                    {
                        bool addIt = true;
                        if(!string.IsNullOrEmpty(this.FileNamePattern))
                        {
                            Regex fileNameRegex=new Regex(this.FileNamePattern,RegexOptions.IgnoreCase);
                            Match fileNameMatch = fileNameRegex.Match(file.Name);
                            if(!fileNameMatch.Success)
                            {
                                addIt = false;
                            }
                        }
                        if (addIt)
                        {
                            HotFolderOutput hotFile =
                                new HotFolderOutput(this.ComponentID, Guid.Empty, file.FullName, FileChangeType.Create);
                            outputCollection.Add(hotFile);
                        }
                    }
                }
            }
            if (outputCollection.Count > 0)
                return outputCollection.ToArray();
            else
                return null;
        }

        public override ResultBase Output
        {
            get { return this._Output; }
            set { this._Output =(HotFolderOutput) value; }
        }

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = base.Serialize(ref xDoc, ref parentNode);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkflowTriggerType", ((int)this.TriggerType).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TimeSpanUnit", ((int)this.TimeSpanUnit).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Interval", this.Interval.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FirstStartTime", this.StartTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "LastRunTime", this.LastRunTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "NextRunTime", this.NextRunTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "IsActive", this.IsActive.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode,"HotFolderPath",this.HotFolderPath);
            XmlDataUtil.UpdateAttribute(ref xDoc,xNode,"FileNamePattern",this.FileNamePattern);
            XmlDataUtil.UpdateAttribute(ref xDoc,xNode,"IncludeSubFolders",this.IncludeSubFolders.ToString());
            return xNode;
        }

        public override WorkflowComponentBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                HotFolderTrigger hotfolder = base.Instantiate(xNode) as HotFolderTrigger;
                hotfolder.TriggerType =
                    (WorkflowTriggerType)int.Parse(xNode.Attributes.GetNamedItem("WorkflowTriggerType").Value);
                hotfolder.TimeSpanUnit = (TimeLapseUnit)int.Parse(xNode.Attributes.GetNamedItem("TimeSpanUnit").Value);
                hotfolder.Interval = int.Parse(xNode.Attributes.GetNamedItem("Interval").Value);
                hotfolder.StartTime = DateTime.Parse(xNode.Attributes.GetNamedItem("FirstStartTime").Value);
                hotfolder.LastRunTime = DateTime.Parse(xNode.Attributes.GetNamedItem("LastRunTime").Value);
                hotfolder.NextRunTime = DateTime.Parse(xNode.Attributes.GetNamedItem("NextRunTime").Value);
                hotfolder.IsActive = bool.Parse(xNode.Attributes.GetNamedItem("IsActive").Value);

                hotfolder.HotFolderPath = xNode.Attributes.GetNamedItem("HotFolderPath").Value;
                hotfolder.FileNamePattern = xNode.Attributes.GetNamedItem("FileNamePattern").Value;
                hotfolder.IncludeSubFolders = bool.Parse(xNode.Attributes.GetNamedItem("IncludeSubFolders").Value);
                return hotfolder;
            }
            else
                throw new Exception("Unable to instantiate Trigger: invalid type specified in xml node");
        }
    }
}
